import { AccessToken } from './../entity/access-token.entity';
import { getRepository } from 'typeorm';
import { CreateTicketDto } from '@dtos/index.dto';
import moment from 'moment';
import { httpGet, httpPost } from '@/http/http';
import config from 'config';
import { qyProps } from '@utils/qy-sdk';
import {
  CorpAccessTokenProps,
  CorpProps,
  DeptInterface,
  DeptListProps,
  MsgDto,
  permanentCodeProps,
  SuiteAccessTokenProps,
  UserDto,
  UserListProps,
} from '@interfaces/index.interface';
import { Wework } from '@entity/wework.entity';
import { Corp } from '@entity/corp.entity';
import { Dept } from '@entity/dept.entity';
import { QyUser } from '@/entity/qy-user.entity';
const { suiteId, suiteSecret }: qyProps = config.get('qy');

class IndexService {
  public accessToken = AccessToken;
  public wework = Wework;
  public corp = Corp;
  public dept = Dept;
  public user = QyUser;

  public async getSuiteAccessToken(): Promise<string> {
    const tokenRepository = getRepository(this.accessToken);
    const token: AccessToken[] = await tokenRepository.find({
      disabled: '0',
    });
    return token[0].suiteAccessToken;
  }

  async saveWeworkMsg(msg: MsgDto) {
    const weworkRepository = getRepository(this.wework);
    await weworkRepository.save(msg);
  }
  async addSuiteTicket(suiteTicket: CreateTicketDto): Promise<AccessToken> {
    const tokenRepository = getRepository(this.accessToken);
    const res = await tokenRepository.findOne({
      disabled: '0',
    });
    if (res) {
      res.ticket = suiteTicket.ticket;
      return await tokenRepository.save(res);
    } else {
      return await tokenRepository.save(suiteTicket);
    }
  }

  async updateSuiteAccessToken(suiteAccessToken: string) {
    const tokenRepository = getRepository(this.accessToken);
    const now = moment().toDate();
    const nextDate = moment().add(2, 'hours').toDate();

    const res = await tokenRepository.findOne({
      disabled: '0',
    });
    if (res) {
      res.suiteAccessToken = suiteAccessToken;
      res.sTokenCreateAt = now;
      res.sTokenExpiresAt = nextDate;
      return await tokenRepository.save(res);
    }
  }

  async checkAndUpdateAccessToken() {
    const tokenRepository = getRepository(this.accessToken);
    const res = await tokenRepository.findOne({
      disabled: '0',
    });
    if (res) {
      const expiresAt = res.sTokenExpiresAt ? moment(res.sTokenExpiresAt) : moment();
      const now = moment();
      const gap = expiresAt.diff(now, 'minutes');
      if (gap <= 20) {
        const accessToken = await this.getAccessToken(res.ticket);
        await this.updateSuiteAccessToken(accessToken);
      }
    }
  }

  // 获取第三方应用凭证
  // https://work.weixin.qq.com/api/doc/90001/90143/90600
  async getAccessToken(suiteTicket: string) {
    const res = await httpPost<SuiteAccessTokenProps>('service/get_suite_token', {
      suite_id: suiteId,
      suite_secret: suiteSecret,
      suite_ticket: suiteTicket,
    });
    return res.data.suite_access_token;
  }

  // // 获取预授权码
  // // https://work.weixin.qq.com/api/doc/90001/90143/90601
  // async getPreAuthCode(suiteAccessToken: string) {
  //   const res = await httpGet<PreAuthCodeProps>(QY_BASE_URL + `get_pre_auth_code?suite_access_token=${suiteAccessToken}`);
  //   return res.data.pre_auth_code;
  // }
  //
  // 获取企业永久授权码
  // https://work.weixin.qq.com/api/doc/90001/90143/90603
  async getPermanentCode(authCode: string) {
    const suiteAccessToken = await this.getSuiteAccessToken();
    const res = await httpPost<permanentCodeProps>(`service/get_permanent_code?suite_access_token=${suiteAccessToken}`, {
      auth_code: authCode,
    });
    return res.data;
  }

  // 保存企业信息
  async saveCorpInfo(corp: CorpProps) {
    const corpRepository = getRepository(this.corp);
    return await corpRepository.save(corp);
  }

  // 获取企业的 access token
  async getCorpAccessToken(corpId: string) {
    const corpRepository = getRepository(this.corp);
    const corpRes = await corpRepository.findOne({
      corpId,
      disabled: '0',
    });
    if (corpRes) {
      const expiresAt = corpRes.accessTokenExpiresAt ? moment(corpRes.accessTokenExpiresAt) : moment();
      const now = moment();
      const gap = expiresAt.diff(now, 'minutes');
      if (gap <= 10) {
        const suiteAccessToken = await this.getSuiteAccessToken();
        const res = await httpPost<CorpAccessTokenProps>(`service/get_corp_token?suite_access_token=${suiteAccessToken}`, {
          auth_corpid: corpId,
          permanent_code: corpRes.permanentCode,
        });
        if (res.data.access_token) {
          await this.updateAccessToken(corpId, res.data.access_token, res.data.expires_in);
          return res.data.access_token;
        } else {
          return '';
        }
      } else {
        return corpRes.accessToken;
      }
    }
  }

  // 调用 wework-server服务新建书馆
  async createlibrary(corpId: string) {
    const res = await httpGet(`http://localhost:5333/v1/api/library/install?corpId=${corpId}`, true);
    return res;
  }

  // 更新 access token
  async updateAccessToken(corpId: string, accessToken: string, expiresIn = 7200) {
    const corpRepository = getRepository(this.corp);
    const corpRes = await corpRepository.findOne({
      corpId,
      disabled: '0',
    });
    if (corpRes) {
      corpRes.accessToken = accessToken;
      corpRes.accessTokenExpiresAt = moment().add(expiresIn, 'seconds').toDate();
      await corpRepository.save(corpRes);
    }
  }

  // 从企业微信获取部门列表
  async getDeptListFromWework(corpId: string, id?: string) {
    const deptRepository = getRepository(this.dept);
    const accessToken = await this.getCorpAccessToken(corpId);
    if (accessToken) {
      const url = id ? `department/list?access_token=${accessToken}&id=${id}` : `department/list?access_token=${accessToken}`;
      const res = await httpGet<DeptListProps>(url);
      if (res.data.department.length > 0) {
        for (let i = 0; i < res.data.department.length; i++) {
          const v = res.data.department[i];
          const dept: DeptInterface = {
            corpId,
            cId: v.id,
            name: v.name,
            parentId: v.parentid,
            order: v.order,
            name_en: v.name_en || '',
          };
          await deptRepository.insert(dept);
        }
      }
      return res.data.department;
    }
  }

  // // 从数据库获取部门列表
  async getDeptListFromDb(corpId: string, id?: string) {
    const deptRepository = getRepository(this.dept);
    const res = await deptRepository.find({ corpId, disabled: '0' });
    for (let i = 0; i < res.length; i++) {
      const v = res[i];
      await this.getDeptMembers(corpId, v.cId);
    }
    return res;
  }

  // 获取部门成员详细信息
  async getDeptMembers(corpId: string, deptId: number, fetchChild = 1) {
    const userRepository = getRepository(this.user);
    const accessToken = await this.getCorpAccessToken(corpId);
    if (accessToken) {
      const url = `user/list?access_token=${accessToken}&department_id=${deptId}&fetch_child=${fetchChild}`;
      const res = await httpGet<UserListProps>(url);
      if (res.data.userlist.length > 0) {
        for (let i = 0; i < res.data.userlist.length; i++) {
          const v = res.data.userlist[i];
          const user: UserDto = {
            corpId,
            userId: v.userid,
            name: v.name,
            department: v.department.join(','),
            gender: v.gender,
            avatar: v.avatar,
            status: v.status,
            order: v.order.join(','),
            mainDepartment: v.main_department,
            isLeaderInDept: v.is_leader_in_dept.join(','),
            thumbAvatar: v.thumb_avatar,
            openUserId: v.open_userid,
          };
          const u = await userRepository.findOne({
            userId: v.userid,
            disabled: '0',
          });
          if (u) {
            user.id = u.id;
          }
          await userRepository.save(user);
        }
      }
      return res.data.userlist;
    }
  }

  // 用户取消授权后，disabled 用户的企业信息
  async disabledCorp(corpId: string) {
    const corpRepository = getRepository(this.corp);
    const deptRepository = getRepository(this.dept);
    const userRepository = getRepository(this.user);
    await corpRepository.update(
      {
        corpId,
      },
      {
        disabled: '1',
      },
    );

    await deptRepository.update(
      {
        corpId,
      },
      {
        disabled: '1',
      },
    );

    await userRepository.update(
      {
        corpId,
      },
      {
        disabled: '1',
      },
    );
  }

  // userId 换 openId
  async convertToOpenId(corpId: string, userId: string) {
    const accessToken = await this.getCorpAccessToken(corpId);
    if (accessToken) {
      const res = await httpPost(`user/convert_to_openid?access_token=${accessToken}`, {
        userid: userId,
      });
      return res;
    }
  }
}

export default IndexService;
